# ******************************************************************************
#  Copyright (c) 2021-2022. Kneron Inc. All rights reserved.                   *
# ******************************************************************************

from os import listdir
from os.path import isfile, join, dirname, abspath, basename
from typing import List
import platform
import abc


class LibLoaderBase:
    EXTENSION_FLAG = '${extension}'

    def __init__(self, package_name: str):
        self._pwd = dirname(abspath(__file__))
        self._kneron_libs = []
        self._share_libs_load_order = []
        self._platform_system = platform.system()
        self._platform_machine = platform.machine()
        self._lib_path = join(self._pwd, '../../{}/lib'.format(package_name if package_name == 'kp' else join('../', package_name)))

        self._init_kneron_libs()
        self._init_share_libs_load_order()

        self.__parse_kneron_libs_extension()
        self.__parse_share_libs_load_order_extension()

        self._share_libs = self.__prepare_share_libs(lib_path=self._lib_path)

    @staticmethod
    def __parse_file_path_from_dir(dir_path: str):
        return [join(dir_path, f) for f in listdir(dir_path) if isfile(join(dir_path, f))]

    def __reorder_load_libs(self, share_libs):
        new_share_libs = []
        share_lib_names = [basename(share_lib) for share_lib in share_libs]

        for share_lib in self._share_libs_load_order:
            if share_lib in share_lib_names:
                new_share_libs.append(share_libs[share_lib_names.index(share_lib)])

        return new_share_libs

    def __prepare_share_libs(self, lib_path):
        share_libs = LibLoaderBase.__parse_file_path_from_dir(dir_path=lib_path)
        return self.__reorder_load_libs(share_libs=share_libs)

    def __parse_libs_extension(self, lib_name: str) -> str:
        if 'Linux' == self._platform_system:
            extension = '.so'
        elif 'Windows' == self._platform_system:
            extension = '.dll'
        elif 'Darwin' == self._platform_system:
            extension = '.dylib'
        else:
            raise EnvironmentError('Error raised in {}. Description: {}'.format(
                'LibLoaderBase',
                'Not Supported Platform - {}'.format(self._platform_system)
            ))

        return lib_name.replace('.{}'.format(LibLoaderBase.EXTENSION_FLAG), extension)

    def __parse_kneron_libs_extension(self) -> str:
        for idx in range(len(self._kneron_libs)):
            self._kneron_libs[idx] = self.__parse_libs_extension(lib_name=self._kneron_libs[idx])

    def __parse_share_libs_load_order_extension(self) -> str:
        for idx in range(len(self._share_libs_load_order)):
            self._share_libs_load_order[idx] = self.__parse_libs_extension(lib_name=self._share_libs_load_order[idx])


    @abc.abstractmethod
    def _init_kneron_libs(self):
        pass

    @abc.abstractmethod
    def _init_share_libs_load_order(self):
        pass

    @property
    def kneron_libs(self) -> List:
        return self._kneron_libs

    @property
    def share_libs(self) -> List:
        return self._share_libs